#include <string.h>

#include "./common/HashTable.h"
#include "./common/YXLog.h"
#include "Route.h"

#include "Http.h"
#include "HttpFixedResponse.h"
#include "HttpResponse.h"
#include "common/Trie.h"

TrieNode *getRoute;
TrieNode *postRoute;
TrieNode *putRoute;
TrieNode *deleteRoute;

__attribute__((constructor(101))) void initRoute() {
    getRoute    = trie_create_node(NULL);
    postRoute   = trie_create_node(NULL);
    putRoute    = trie_create_node(NULL);
    deleteRoute = trie_create_node(NULL);
}

static BeforeRouteHandlerWarpper *createBeforeRouteHandlerWarrper(BeforeRouteHandler handler);
static void                       addToBeforeRouteHandlerLinkedList(EnhancedRouteHandler      *enhancedRouteHandler,
                                                                    BeforeRouteHandlerWarpper *handler);
static YXResult *parseRequestBodyBeforeHandler(Request *request, Response *response, void *privateData);
static YXResult *pathVariableBeforeHandler(Request *request, Response *response, void *privateData);


static BeforeRouteHandlerWarpper *createBeforeRouteHandlerWarrper(BeforeRouteHandler handler) {
    BeforeRouteHandlerWarpper *beforeRouteHandlerWarpper = malloc(sizeof(BeforeRouteHandlerWarpper));
    beforeRouteHandlerWarpper->handler                   = handler;
    beforeRouteHandlerWarpper->next                      = NULL;
    beforeRouteHandlerWarpper->privateData               = NULL;

    return beforeRouteHandlerWarpper;
}

static void addToBeforeRouteHandlerLinkedList(EnhancedRouteHandler      *enhancedRouteHandler,
                                              BeforeRouteHandlerWarpper *handler) {
    if (enhancedRouteHandler->beforeRouteHandlerLinkedList == NULL) {
        enhancedRouteHandler->beforeRouteHandlerLinkedList = handler;
    } else {
        BeforeRouteHandlerWarpper *current = enhancedRouteHandler->beforeRouteHandlerLinkedList;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = handler;
    }
}

static YXResult *parseRequestBodyBeforeHandler(Request *request, Response *response, void *privateData) {
    if (strcmp(request->content_type, MIME_TYPE_JSON) == 0) {
        cJSON *json = cJSON_Parse(request->body);
        logError("%s", cJSON_Print(json));
        if (json == NULL) {
            set_response_status(response, HTTP_BAD_REQUEST);
            return YXResultUtils.error("不合法的JSON格式！");
        }
        request->parsed_data = json;
    }
    return NULL;
}

static YXResult *pathVariableBeforeHandler(Request *request, Response *response, void *privateData) {
    PathVariblePrivateData *pathVariblePrivateData = privateData;
    char                  **arr                    = malloc(sizeof(char *) * (pathVariblePrivateData->count));

    // 分割字符串
    for (int i = 0; i < pathVariblePrivateData->count; i++) {
        arr[i] = strtok(request->path + pathVariblePrivateData->start, "/");
    }

    request->parsed_data = arr;

    return NULL;
}

/**
 * 目前只有一个注解的情况也就是只会有一个 beforeRouteHandler
 */
void addRoute(char *method, char *path, char *annotation, RouteHandler handler) {
    EnhancedRouteHandler *enhancedRoutehandler         = malloc(sizeof(EnhancedRouteHandler));
    enhancedRoutehandler->mainHandler                  = handler;
    enhancedRoutehandler->beforeRouteHandlerLinkedList = NULL;

    if (annotation != NULL) {
        if (strcmp(annotation, REQUEST_BODY_ANNOTATION) == 0) {
            BeforeRouteHandlerWarpper *beforeRouteHandlerWarpper =
                    createBeforeRouteHandlerWarrper(parseRequestBodyBeforeHandler);
            addToBeforeRouteHandlerLinkedList(enhancedRoutehandler, beforeRouteHandlerWarpper);
        } else if (strcmp(annotation, PATH_VARIABLE_ANNOTATION) == 0) {
            BeforeRouteHandlerWarpper *beforeRouteHandlerWarpper =
                    createBeforeRouteHandlerWarrper(pathVariableBeforeHandler);
            addToBeforeRouteHandlerLinkedList(enhancedRoutehandler, beforeRouteHandlerWarpper);
            PathVariblePrivateData *privateData                             = malloc(sizeof(PathVariblePrivateData));
            enhancedRoutehandler->beforeRouteHandlerLinkedList->privateData = privateData;
            // 记录起始位置提高解析效率
            int cnt = 0;
            for (int i = 0; i < strlen(path); i++) {
                if (path[i] == '{') {
                    if (cnt == 0) {
                        privateData->start = i;
                    }
                    cnt++;
                }
            }
            privateData->count = cnt;
            if (privateData->count == 0) {
                logFatal("你使用了 @PathVariable 但是没有在路径中定义变量");
            }
            // 修改path为通配符
            char* newPath = malloc(sizeof(char) * privateData->start + 3);
            memcpy(newPath, path, privateData->start);
            newPath[privateData->start] = '*';
            newPath[privateData->start + 1] = '*';
            newPath[privateData->start + 2] = '\0';
            path = newPath;

        } else {
            logFatal("不支持的注解: %s", annotation);
        }
    }

    if (strcmp(method, "GET") == 0) {
        trie_insert(getRoute, path, enhancedRoutehandler);
    } else if (strcmp(method, "PUT") == 0) {
        trie_insert(putRoute, path, enhancedRoutehandler);
    } else if (strcmp(method, "POST") == 0) {
        trie_insert(postRoute, path, enhancedRoutehandler);
    } else if (strcmp(method, "DELETE") == 0) {
        trie_insert(deleteRoute, path, enhancedRoutehandler);
    } else {
        logFatal("不支持的 Http 方法: %s", method);
    }
}

EnhancedRouteHandler* getGetRouteHandler(char *path) { return trie_starts_with_prefix(getRoute, path); }

EnhancedRouteHandler* getPostRouteHandler(char *path) { return trie_starts_with_prefix(postRoute, path); }

EnhancedRouteHandler* getPutRouteHandler(char *path) { return trie_starts_with_prefix(putRoute, path); }

EnhancedRouteHandler* getDeleteRouteHandler(char *path) { return trie_starts_with_prefix(deleteRoute, path); }